package org.jsbd.boss.action;

import java.io.File;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jsbd.boss.common.DataGridModel;
import org.jsbd.boss.common.ResponseUtils;
import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.domian.ChannelApkInfo;
import org.jsbd.boss.domian.ChannelProvinceInfo;
import org.jsbd.boss.domian.ProvinceInfo;
import org.jsbd.boss.domian.channel.ChannelApkConfig;
import org.jsbd.boss.service.IChannelApkInfoService;
import org.jsbd.boss.service.IInterceptInfoService;
import org.jsbd.boss.service.impl.ChannelConfigService;
import org.jsbd.boss.util.CacheKey;
import org.jsbd.boss.util.DateUtil;
import org.jsbd.boss.util.ManifestUtils;
import org.jsbd.boss.util.PropertiesUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import edu.hziee.cap.common.util.Md5Utils;

@Controller
@RequestMapping("/channelapk")
public class ConfigController {
	public static final Logger LOGGER = LoggerFactory.getLogger(ConfigController.class);

	@Autowired
	private ChannelConfigService channelConfigService;

	@Autowired
	private IChannelApkInfoService channelApkInfoService;

	@Resource
	private RedisClient redisClient;

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String configList(Model model) {
		return "channelapk/configList";
	}

	@RequestMapping(value = "/provinceconfigList", method = RequestMethod.GET)
	public String provinceconfigList(Model model) {
		return "channelapk/provinceconfigList";
	}

	// 基本配置查询展示接口
	@RequestMapping(value = "/configList", params = "json")
	@ResponseBody
	public Map<String, Object> configPageList(DataGridModel model, ChannelApkInfo form) {
		form = (form == null ? new ChannelApkInfo() : form);
		form.setPageInfo(model);
		
		String apkName = form.getApkName();
		if (StringUtils.isNotBlank(apkName)) {
			String[] marks = apkName.split(" ");
			List<String> keywords = new ArrayList<>();
			for (String keyword : marks) {
				keywords.add(keyword);
			}
			form.setKeywords(keywords);
		}
		
		Map<String, Object> map = channelConfigService.getAllChannelInfo(form);
		List<ChannelApkInfo> configList = (List<ChannelApkInfo>) map.get("rows");
		map.put("rows", configList);
		return map;
	}

	// 跳出新增页面
	@RequestMapping(value = "/addConfig", method = RequestMethod.GET)
	public String addConfig(Model model, HttpServletResponse response) {
		return "channelapk/add";
	}

	@ResponseBody
	@RequestMapping(value = "/saveConfig", method = RequestMethod.POST)
	public void saveConfig(ChannelApkInfo configInfo, @RequestParam MultipartFile[] file, HttpServletResponse response, HttpServletRequest request) {
		Map<String, String> map = uploadFile(file, request);
		configInfo.setApkpath(map.get("path0"));
		configInfo.setJarpath(map.get("path1"));
		configInfo.setScriptpath(map.get("path2"));
		String packageName = (map.get("packageName"));
		String apkmd5 = (map.get("apkmd5"));
		configInfo.setMark(packageName + "-" + apkmd5);
		channelConfigService.saveChannelInfo(configInfo);
		ResponseUtils.responseSuccess(response);
	}

	@ResponseBody
	@RequestMapping(value = "/updateConfig", method = RequestMethod.POST)
	public void updateConfig(ChannelApkInfo configInfo, @RequestParam MultipartFile[] file, HttpServletResponse response, HttpServletRequest request) {
		channelConfigService.saveChannelInfo(configInfo);
		ResponseUtils.responseSuccess(response);
	}

	// 省份查询展示接口
	@RequestMapping(value = "/{mark}/provinceUpdate")
	public String updateProvince(@PathVariable String mark, Model model) {
		LOGGER.info("updateProvince,mark is [{}]", mark);
		ChannelApkInfo channelApkInfo = channelConfigService.getProvinceByMarkForPage(mark);

		if (channelApkInfo != null && StringUtils.isNotBlank(channelApkInfo.getProvinceIds())) {
			String province = channelApkInfo.getProvinceIds();
			List<String> list = Arrays.asList(province.split(","));
			model.addAttribute("openProvinceList", list);
		}
		List<ProvinceInfo> provinceList = channelConfigService.getProvinceInfoList();
		model.addAttribute("provinceList", provinceList);
		return "channelapk/addProvince";
	}

	@RequestMapping(value = "/saveProvince", method = RequestMethod.POST)
	public void saveProvince(Model model, String mark, String openProvince, HttpServletResponse response) {
		if (mark == null) {
			ResponseUtils.responseFailure(response);
		}
		// 更新操作
		channelConfigService.updateProvinceByMark(mark, openProvince);
		ResponseUtils.responseSuccess(response);
	}

	@ResponseBody
	@RequestMapping(value = "/delete", method = RequestMethod.GET)
	public void delete(String mark, HttpServletResponse response) {
		channelConfigService.deleteByMark(mark);
		ResponseUtils.responseSuccess(response);
	}

	@ResponseBody
	@RequestMapping(value = "/provinceDelete", method = RequestMethod.GET)
	public void provincedelete(String mark, String provinceid, String privinceid, HttpServletResponse response) {
		channelConfigService.deleteProvinceBymarkAndid(mark, provinceid);
		ResponseUtils.responseSuccess(response);
	}

	@RequestMapping(value = "/{mark}/configUpdate")
	public String configUpdate(@PathVariable String mark, Model model) {
		LOGGER.info("configUpdate,mark is [{}]", mark);
		ChannelApkInfo channelApkInfo = channelConfigService.getProvinceByMarkForPage(mark);
		model.addAttribute("config", channelApkInfo);
		// List<InterceptInfo> interceptList =
		// channelConfigService.getInterceptInfoByChannelApkInfo(channelApkInfo);
		// model.addAttribute("interceptList", interceptList);
		return "channelapk/updateConfig";
	}

	/*
	 * //进入留存查询展示接口
	 * 
	 * @RequestMapping(value = "/{mark}/retentList", method = RequestMethod.GET)
	 * public String retentPageList(Model model, @PathVariable String mark){
	 * ConfigDO configDO = configService.getConfigByMark(mark); if(configDO ==
	 * null){ LOGGER.info("没有该apk的配置信息，请检查mark:",mark); return
	 * "无法根据mark值查到相应apk信息"; }
	 * 
	 * List<RetentDO> retentList = configService.getRetentListByMark(mark);
	 * //为了让页面显示28条数据，只能提前把数据加上 if(retentList.size()==0){ for(int i =
	 * 1;i<29;i++){ RetentDO retent = new RetentDO();
	 * retent.setApkName(configDO.getApkName());
	 * retent.setChannelName(configDO.getChannelName());
	 * retent.setMark(configDO.getMark()); retent.setRetentDay(i);
	 * retent.setRetentRate(100); configService.insertRetent(retent); } }
	 * 
	 * model.addAttribute("mark",mark); return "customization/retentConfig"; }
	 * 
	 * //显示数据接口
	 * 
	 * @RequestMapping(value = "/retentList")
	 * 
	 * @ResponseBody public Map<String, Object> retentPageList(DataGridModel
	 * model,RetentDO form){ Map<String, Object> map =
	 * configService.findRetentPageList(model, form); List<RetentDO> retrntList
	 * = (List<RetentDO>) map.get("rows"); map.put("rows", retrntList); return
	 * map; }
	 * 
	 * @RequestMapping(value = "/saveRetent", method = RequestMethod.POST)
	 * public void saveRetent(Model model,HttpServletResponse response) { //
	 * //更新操作 int flag = 0; if(flag >0){
	 * ResponseUtils.responseSuccess(response); }else{
	 * ResponseUtils.responseFailure(response); } }
	 */

	// 基本配置查询展示接口
	@RequestMapping(value = "/provinceconfigList", params = "json")
	@ResponseBody
	public Map<String, Object> provinceconfigPageList(DataGridModel model, ChannelProvinceInfo form) {
		form = (form == null ? new ChannelProvinceInfo() : form);
		form.setPageInfo(model);
		String provinceId = form.getProvinceid();
		if (provinceId != null && "-1".equals(provinceId)) {
			form.setProvinceid(null);
		}
		
		String mark = form.getMark();
		if (StringUtils.isNotBlank(mark)) {
			String[] marks = mark.split(" ");
			List<String> keywords = new ArrayList<>();
			for (String keyword : marks) {
				keywords.add(keyword);
			}
			form.setKeywords(keywords);
		}
		
		return channelConfigService.selectConfigPageListMap(form);
	}

	// 基本配置查询展示接口
	@RequestMapping(value = "/provinceRateUpdate")
	@ResponseBody
	public int provinceRateUpdate(HttpServletRequest request, HttpServletResponse resp) {
		ChannelProvinceInfo form = new ChannelProvinceInfo();
		form.setMark(request.getParameter("mark"));
		form.setProvinceid(request.getParameter("provinceid"));
		form.setProvinceRate(Integer.parseInt(request.getParameter("provinceRate")));
		return channelConfigService.updateProvinceRate(form);
	}

	/**
	 * 上传文件
	 * 
	 * @return
	 */
	public Map<String, String> uploadFile(MultipartFile[] myfiles, HttpServletRequest request) {
		Map<String, String> map = new HashMap<String, String>();
		int i = 0;
		String fileUploadPath = PropertiesUtil.getValue("game_file_upload_path");
		for (MultipartFile myfile : myfiles) {
			if (myfile.isEmpty()) {
				LOGGER.error("文件未上传");
			} else {
				String originalFilename = myfile.getOriginalFilename();
				String fileName = originalFilename.substring(originalFilename.lastIndexOf("/") + 1, originalFilename.length());
				int fileLen = fileName.length();
				String fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileLen);
				// 如果用的是Tomcat服务器，则文件会上传到\\%TOMCAT_HOME%\\webapps\\YourWebProject\\WEB-INF\\upload\\文件夹中
				String fileSaveName = System.currentTimeMillis() + fileName;
				File apkFile = new File(fileUploadPath, fileSaveName);
				try {
					// 这里不必处理IO流关闭的问题，因为FileUtils.copyInputStreamToFile()方法内部会自动把用到的IO流关掉
					FileUtils.copyInputStreamToFile(myfile.getInputStream(), apkFile);
					if ("apk".equals(fileType)) {
						String packageName = parseApk(apkFile);
						map.put("packageName", packageName);
						map.put("apkmd5", Md5Utils.md5Hex(FileUtils.readFileToByteArray(apkFile)));
					}
					map.put("path" + i, fileUploadPath + "/" + fileSaveName);
					i++;
				} catch (Exception e) {
					LOGGER.error(e.getMessage(), e);
				}
			}
		}
		return map;
	}

	public String parseApk(File f) throws Exception {
		String packageName = "";
		ZipFile zip = new ZipFile(f);
		Enumeration<?> enu = zip.entries();
		while (enu.hasMoreElements()) {
			ZipEntry ent = (ZipEntry) enu.nextElement();
			String entName = ent.getName();
			if (entName.endsWith("AndroidManifest.xml")) {
				Map<String, String> map = ManifestUtils.parseAxml(zip.getInputStream(ent)); // 获取文件信息
				packageName = map.get("package");
			}
		}
		zip.close();
		return packageName;
	}


	@RequestMapping(value = "/flushRetentCache")
	@ResponseBody
	public void flushRetentCache(String start, Integer type) throws Exception {
		Integer preDay = Integer.parseInt(DateUtil.getCurrentDateStr()) - 1;
		Set<String> days = DateUtil.getDatesBetweenTwoDate(start, preDay + "");
		List<ChannelApkConfig> apks = channelApkInfoService.selectAllApkInfos();
		for (String day : days) {
			long dayKey = DateUtil.getPreDaysOfTime(day);
			for (int i = 1; i <= 60; i++) {
				String currday = DateUtil.getPreDay(i, day);
				for (ChannelApkConfig config : apks) {
					String taskQueueKey = CacheKey.R_T_Q_D_KEY + dayKey + config.getMark() + currday;
					if (type == 1) {
						redisClient.expire(taskQueueKey, DateUtil.leftTimeToMidNight());
						LOGGER.warn("expire cacheKey {} ", taskQueueKey);
					} else {
						redisClient.remove(taskQueueKey);
						LOGGER.warn("del cacheKey {} ", taskQueueKey);
					}
				}
				Thread.sleep(200);
			}
		}
	}

}
